"""
混合温度处理器
集成TSDK精确处理和HSV估算两种方法
"""

import os
import cv2
import numpy as np
from typing import Dict, Any, Optional, Tuple, List
import logging

from .tsdk_processor import get_tsdk_processor, TSDKProcessor
from .temperature_mapper import TemperatureMapper


class HybridTemperatureProcessor:
    """混合温度处理器，支持多种温度分析方法"""
    
    def __init__(self):
        self.tsdk_processor = get_tsdk_processor()
        self.hsv_mapper = TemperatureMapper()
        self.logger = logging.getLogger(__name__)
        
        # 当前处理模式
        self.current_mode = None
        self.current_data = None
        
    def process_image(self, image_path: str, force_mode: str = None) -> Dict[str, Any]:
        """
        处理热成像图像
        
        Args:
            image_path: 图像文件路径
            force_mode: 强制使用的处理模式 ('tsdk', 'hsv', 'auto')
            
        Returns:
            Dict: 处理结果
        """
        if not os.path.exists(image_path):
            raise FileNotFoundError(f"文件不存在: {image_path}")
        
        # 确定处理模式
        if force_mode:
            mode = force_mode.lower()
        else:
            mode = self._detect_processing_mode(image_path)
        
        self.logger.info(f"使用处理模式: {mode}")
        
        if mode == 'tsdk':
            return self._process_with_tsdk(image_path)
        elif mode == 'hsv':
            return self._process_with_hsv(image_path)
        elif mode == 'hybrid':
            return self._process_hybrid(image_path)
        elif mode == 'auto':
            # 自动模式，重新检测
            detected_mode = self._detect_processing_mode(image_path)
            self.logger.info(f"自动检测到处理模式: {detected_mode}")
            return self.process_image(image_path, force_mode=detected_mode)
        else:
            raise ValueError(f"不支持的处理模式: {mode}")
    
    def _detect_processing_mode(self, image_path: str) -> str:
        """自动检测最佳处理模式"""
        # 检查是否为R-JPEG文件
        if self._is_rjpeg_format(image_path):
            # 尝试初始化TSDK
            if not self.tsdk_processor.sdk_initialized:
                self.tsdk_processor.initialize_sdk()
            
            if self.tsdk_processor.sdk_initialized:
                return 'tsdk'
        
        # 默认使用HSV模式
        return 'hsv'
    
    def _is_rjpeg_format(self, image_path: str) -> bool:
        """检查是否为R-JPEG格式"""
        try:
            with open(image_path, 'rb') as f:
                header = f.read(1024)
                # 检查R-JPEG特征
                return (b'FLIR' in header or 
                       b'DJI' in header or 
                       image_path.lower().endswith(('.r.jpg', '.rjpeg')))
        except Exception:
            return False
    
    def _process_with_tsdk(self, image_path: str) -> Dict[str, Any]:
        """使用TSDK处理"""
        try:
            # 确保TSDK已初始化
            if not self.tsdk_processor.sdk_initialized:
                self.tsdk_processor.initialize_sdk()
            
            result = self.tsdk_processor.process_rjpeg_file(image_path)
            result['processing_method'] = 'tsdk'
            result['accuracy_level'] = 'high'  # TSDK提供高精度数据
            
            self.current_mode = 'tsdk'
            self.current_data = result
            
            return result
            
        except Exception as e:
            self.logger.warning(f"TSDK处理失败，回退到HSV模式: {e}")
            return self._process_with_hsv(image_path)
    
    def _process_with_hsv(self, image_path: str) -> Dict[str, Any]:
        """使用HSV颜色映射处理"""
        try:
            # 使用cv2.imdecode处理中文路径和特殊格式文件
            try:
                # 方法1：直接读取（适用于普通图片）
                image = cv2.imread(image_path, cv2.IMREAD_COLOR)
                if image is None:
                    # 方法2：使用imdecode处理中文路径和特殊格式
                    with open(image_path, 'rb') as f:
                        image_data = f.read()
                    image_array = np.frombuffer(image_data, dtype=np.uint8)
                    image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
                    
                if image is None:
                    raise ValueError(f"无法读取图像文件: {image_path}")
                    
            except Exception as e:
                self.logger.error(f"图像读取失败: {e}")
                raise ValueError(f"无法读取图像: {image_path} - {str(e)}")
            
            # 转换为HSV
            hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
            height, width = image.shape[:2]
            
            # 生成温度矩阵
            temp_matrix = np.zeros((height, width), dtype=np.float32)
            
            for y in range(height):
                for x in range(width):
                    hsv_pixel = hsv_image[y, x]
                    temp_matrix[y, x] = self.hsv_mapper.color_to_temperature(hsv_pixel)
            
            result = {
                'temperature_matrix': temp_matrix,
                'visible_image': image,
                'width': width,
                'height': height,
                'file_path': image_path,
                'processing_method': 'hsv',
                'processing_mode': 'hsv_mapping',
                'accuracy_level': 'medium',  # HSV估算精度中等
                'min_temp': float(np.min(temp_matrix)),
                'max_temp': float(np.max(temp_matrix)),
                'mean_temp': float(np.mean(temp_matrix)),
                'calibration_points_count': len(self.hsv_mapper.calibration_points)
            }
            
            self.current_mode = 'hsv'
            self.current_data = result
            
            return result
            
        except Exception as e:
            self.logger.error(f"HSV处理失败: {e}")
            raise
    
    def _process_hybrid(self, image_path: str) -> Dict[str, Any]:
        """混合处理模式"""
        try:
            # 先尝试TSDK
            tsdk_result = self._process_with_tsdk(image_path)
            
            # 再进行HSV处理作为对比
            hsv_result = self._process_with_hsv(image_path)
            
            # 合并结果
            result = {
                'temperature_matrix': tsdk_result['temperature_matrix'],
                'visible_image': tsdk_result['visible_image'],
                'width': tsdk_result['width'],
                'height': tsdk_result['height'],
                'file_path': image_path,
                'processing_method': 'hybrid',
                'accuracy_level': 'very_high',
                'tsdk_data': {
                    'min_temp': tsdk_result['min_temp'],
                    'max_temp': tsdk_result['max_temp'],
                    'mean_temp': tsdk_result['mean_temp']
                },
                'hsv_data': {
                    'min_temp': hsv_result['min_temp'],
                    'max_temp': hsv_result['max_temp'],
                    'mean_temp': hsv_result['mean_temp']
                }
            }
            
            # 计算两种方法的差异
            temp_diff = np.abs(tsdk_result['temperature_matrix'] - hsv_result['temperature_matrix'])
            result['method_comparison'] = {
                'mean_difference': float(np.mean(temp_diff)),
                'max_difference': float(np.max(temp_diff)),
                'correlation': float(np.corrcoef(
                    tsdk_result['temperature_matrix'].flatten(),
                    hsv_result['temperature_matrix'].flatten()
                )[0, 1])
            }
            
            self.current_mode = 'hybrid'
            self.current_data = result
            
            return result
            
        except Exception as e:
            self.logger.warning(f"混合处理失败，使用HSV模式: {e}")
            return self._process_with_hsv(image_path)
    
    def add_calibration_point(self, x: int, y: int, temperature: float) -> bool:
        """添加标定点（主要用于HSV模式）"""
        try:
            if self.current_data is None:
                raise RuntimeError("没有当前处理的图像数据")
            
            # 获取该点的HSV颜色
            image = self.current_data['visible_image']
            hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
            hsv_color = hsv_image[y, x]
            
            # 添加到HSV映射器
            self.hsv_mapper.add_calibration_point(
                hsv_color, 
                temperature, 
                position=(x, y)
            )
            
            self.logger.info(f"添加标定点: ({x}, {y}) = {temperature}°C")
            return True
            
        except Exception as e:
            self.logger.error(f"添加标定点失败: {e}")
            return False
    
    def get_calibration_info(self) -> List[Dict[str, Any]]:
        """获取标定点信息"""
        return self.hsv_mapper.get_calibration_info()
    
    def clear_calibration_points(self):
        """清空标定点"""
        self.hsv_mapper.clear_calibration_points()
    
    def get_temperature_at_point(self, x: int, y: int) -> Dict[str, float]:
        """获取指定点的温度"""
        if self.current_data is None:
            raise RuntimeError("没有当前图像数据")
        
        temp_matrix = self.current_data['temperature_matrix']
        temp_height, temp_width = temp_matrix.shape
        
        # 检查是否需要坐标映射（可见光图像与热成像数据分辨率不匹配）
        visible_image = self.current_data.get('visible_image')
        if visible_image is not None:
            vis_height, vis_width = visible_image.shape[:2]
            
            # 如果分辨率不同，需要坐标映射
            if vis_width != temp_width or vis_height != temp_height:
                # 计算缩放比例
                scale_x = temp_width / vis_width
                scale_y = temp_height / vis_height
                
                # 映射坐标到温度矩阵
                temp_x = int(x * scale_x)
                temp_y = int(y * scale_y)
                
                self.logger.info(f"坐标映射: 可见光({x},{y}) -> 热成像({temp_x},{temp_y}), 比例({scale_x:.3f},{scale_y:.3f})")
                
                # 边界检查
                temp_x = max(0, min(temp_width - 1, temp_x))
                temp_y = max(0, min(temp_height - 1, temp_y))
                
                x, y = temp_x, temp_y
        
        # 最终边界检查
        if x < 0 or x >= temp_width or y < 0 or y >= temp_height:
            raise ValueError(f"坐标超出温度矩阵范围: ({x}, {y}), 矩阵尺寸: {temp_width}x{temp_height}")
        
        result = {
            'temperature': float(temp_matrix[y, x]),
            'method': self.current_mode,
            'mapped_coordinates': {'x': x, 'y': y}
        }
        
        # 如果是混合模式，提供两种方法的结果
        if self.current_mode == 'hybrid':
            # 重新计算HSV温度
            image = self.current_data['visible_image']
            hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
            hsv_temp = self.hsv_mapper.color_to_temperature(hsv_image[y, x])
            
            result['tsdk_temperature'] = result['temperature']
            result['hsv_temperature'] = float(hsv_temp)
            result['difference'] = abs(result['tsdk_temperature'] - result['hsv_temperature'])
        
        return result
    
    def get_region_temperature_stats(self, x1: int, y1: int, x2: int, y2: int) -> Dict[str, Any]:
        """获取区域温度统计"""
        if self.current_data is None:
            raise RuntimeError("没有当前图像数据")
        
        temp_matrix = self.current_data['temperature_matrix']
        temp_height, temp_width = temp_matrix.shape
        
        # 检查是否需要坐标映射
        visible_image = self.current_data.get('visible_image')
        if visible_image is not None:
            vis_height, vis_width = visible_image.shape[:2]
            
            # 如果分辨率不同，需要坐标映射
            if vis_width != temp_width or vis_height != temp_height:
                scale_x = temp_width / vis_width
                scale_y = temp_height / vis_height
                
                # 映射区域坐标
                x1 = int(x1 * scale_x)
                y1 = int(y1 * scale_y)
                x2 = int(x2 * scale_x)
                y2 = int(y2 * scale_y)
                
                self.logger.info(f"区域坐标映射: 比例({scale_x:.3f},{scale_y:.3f})")
        
        # 确保坐标正确且在范围内
        x1, x2 = min(x1, x2), max(x1, x2)
        y1, y2 = min(y1, y2), max(y1, y2)
        
        # 边界限制
        x1 = max(0, min(temp_width - 1, x1))
        y1 = max(0, min(temp_height - 1, y1))
        x2 = max(0, min(temp_width, x2))
        y2 = max(0, min(temp_height, y2))
        
        # 提取区域
        region = temp_matrix[y1:y2, x1:x2]
        
        if region.size == 0:
            raise ValueError("区域为空")
        
        # 基础统计
        stats = {
            'min_temp': float(np.min(region)),
            'max_temp': float(np.max(region)),
            'mean_temp': float(np.mean(region)),
            'std_temp': float(np.std(region)),
            'median_temp': float(np.median(region)),
            'method': self.current_mode
        }
        
        # 找到极值位置
        min_pos = np.unravel_index(np.argmin(region), region.shape)
        max_pos = np.unravel_index(np.argmax(region), region.shape)
        
        stats['min_position'] = {'x': x1 + min_pos[1], 'y': y1 + min_pos[0]}
        stats['max_position'] = {'x': x1 + max_pos[1], 'y': y1 + max_pos[0]}
        
        return stats
    
    def export_temperature_data(self, output_path: str, format: str = 'csv') -> bool:
        """导出温度数据"""
        if self.current_data is None:
            raise RuntimeError("没有当前图像数据")
        
        try:
            temp_matrix = self.current_data['temperature_matrix']
            
            if format.lower() == 'csv':
                np.savetxt(output_path, temp_matrix, delimiter=',', fmt='%.2f')
            elif format.lower() == 'npy':
                np.save(output_path, temp_matrix)
            elif format.lower() == 'json':
                import json
                export_data = {
                    'temperature_data': temp_matrix.tolist(),
                    'metadata': {
                        'width': self.current_data['width'],
                        'height': self.current_data['height'],
                        'processing_method': self.current_mode,
                        'min_temp': float(np.min(temp_matrix)),
                        'max_temp': float(np.max(temp_matrix)),
                        'mean_temp': float(np.mean(temp_matrix))
                    }
                }
                
                with open(output_path, 'w', encoding='utf-8') as f:
                    json.dump(export_data, f, indent=2, ensure_ascii=False)
            else:
                raise ValueError(f"不支持的导出格式: {format}")
            
            return True
            
        except Exception as e:
            self.logger.error(f"导出数据失败: {e}")
            return False
    
    def get_processing_capabilities(self) -> Dict[str, bool]:
        """获取处理能力"""
        # 检查TSDK是否可用
        tsdk_available = False
        try:
            if not self.tsdk_processor.sdk_initialized:
                self.tsdk_processor.initialize_sdk()
            tsdk_available = self.tsdk_processor.sdk_initialized
        except Exception:
            pass
        
        return {
            'tsdk_available': tsdk_available,
            'hsv_available': True,
            'hybrid_available': tsdk_available,
            'calibration_support': True,
            'real_time_processing': True
        }
    
    def cleanup(self):
        """清理资源"""
        if self.tsdk_processor:
            self.tsdk_processor.cleanup()
        
        self.current_mode = None
        self.current_data = None


# 全局混合处理器实例
_hybrid_processor = None

def get_hybrid_processor() -> HybridTemperatureProcessor:
    """获取全局混合处理器实例"""
    global _hybrid_processor
    if _hybrid_processor is None:
        _hybrid_processor = HybridTemperatureProcessor()
    return _hybrid_processor